package cn.wgx.commons.security.shiro.filter;

import cn.wgx.commons.security.shiro.realm.CustomRealm;
import cn.wgx.commons.security.shiro.token.CustomUsernamePasswordToken;
import cn.wgx.commons.util.Servlets;
import cn.wgx.commons.util.StringUtils;
import cn.wgx.commons.util.Validation;
import cn.wgx.modules.sys.util.LogUtil;
import cn.wgx.modules.sys.util.UserUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * 登录过滤器
 * 表单验证（包含验证码）过滤类
 */

public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {

	public static final String DEFAULT_LOGIN_TYPE = "loginType";
	public static final String DEFAULT_MESSAGE_PARAM = "message";
	public static final String DEFAULT_CAPTCH = "validateCode";


	/**
	 * 进入
	 * @param request
	 * @param response
	 * @return
	 */
	protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
		String username = getUsername(request);
		String password = getPassword(request);
		if (password==null){
			password = "";
		}
		boolean rememberMe = isRememberMe(request);
		String host = Servlets.getRemoteAddr((HttpServletRequest)request);
		int loginType = getLoginType(request);
		String captcha = WebUtils.getCleanParam(request, DEFAULT_CAPTCH);
		return new CustomUsernamePasswordToken(username, password.toCharArray(), rememberMe, host, loginType, captcha);
	}

	//登录方式: 1:用户名登录,2:邮箱登录,3:手机号登录.默认为1
	private int getLoginType(ServletRequest request) {
		Integer loginType = 1;
		String username = getUsername(request);
		if(Validation.isEmail(username)){
			loginType = 2;
		}else if(Validation.isMobile(username)){
			loginType = 3;
		}else{
			String l = WebUtils.getCleanParam(request, DEFAULT_LOGIN_TYPE);
			try {
				loginType = Integer.parseInt(l);
			} catch (NumberFormatException e) {
				//e.printStackTrace();
			}
		}
		return loginType;
	}

	/**
	 * 获取登录用户名
	 */
	protected String getUsername(ServletRequest request) {
		String username = super.getUsername(request);
		if (StringUtils.isBlank(username)){
			username = StringUtils.toString(request.getAttribute(getUsernameParam()), StringUtils.EMPTY);
		}
		return username;
	}
	
	/**
	 * 获取登录密码
	 */
	@Override
	protected String getPassword(ServletRequest request) {
		String password = super.getPassword(request);
		if (StringUtils.isBlank(password)){
			password = StringUtils.toString(request.getAttribute(getPasswordParam()), StringUtils.EMPTY);
		}
		return password;
	}
	
	/**
	 * 获取记住我
	 */
	@Override
	protected boolean isRememberMe(ServletRequest request) {
		String isRememberMe = WebUtils.getCleanParam(request, getRememberMeParam());
		if (StringUtils.isBlank(isRememberMe)){
			isRememberMe = StringUtils.toString(request.getAttribute(getRememberMeParam()), "true");
		}
		return StringUtils.toBoolean(isRememberMe);
	}

	
	/**
	 * 登录成功之后跳转URL
	 */
	public String getSuccessUrl() {
		return super.getSuccessUrl();
	}
	
	@Override
	protected void issueSuccessRedirect(ServletRequest request,
			ServletResponse response) throws Exception {
//		Principal p = UserUtil.getPrincipal();
//		if (p != null && !p.isMobileLogin()){
			 WebUtils.issueRedirect(request, response, getSuccessUrl(), null, true);
//		}else{
//			super.issueSuccessRedirect(request, response);
//		}
	}

	/**
	 * 登录成功调用事件
	 */
	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response)
			throws Exception {
		//设置user信息进session
		CustomRealm.Principal principal = (CustomRealm.Principal)subject.getPrincipal();
		UserUtil.putCache(UserUtil.SESSION_USER, principal.getUser());
		//登录成功日志记录
		LogUtil.saveLog((HttpServletRequest) request, null, null, "登录成功");
		Cookie[] cookies = ((HttpServletRequest) request).getCookies();
		return super.onLoginSuccess(token, subject, request, response);
	}

	/**
	 * 登录失败调用事件
	 */
	@Override
	protected boolean onLoginFailure(AuthenticationToken token,
                                     AuthenticationException e, ServletRequest request, ServletResponse response) {
		String className = e.getClass().getName(), message = "";
		String errorMsg = e.getMessage();
		if (IncorrectCredentialsException.class.getName().equals(className)
				|| UnknownAccountException.class.getName().equals(className)){
			message = "用户或密码错误, 请重试.";
		}else if (errorMsg != null && StringUtils.startsWith(errorMsg, "msg:")){
			message = StringUtils.replace(errorMsg, "msg:", "");
		}else{
			message = "登录系统出现点问题，请稍后再试！";
			e.printStackTrace(); // 输出到控制台
		}
        request.setAttribute(getFailureKeyAttribute(), className);
        request.setAttribute(getMessageParam(), message);
        //登录失败日志记录
		LogUtil.saveLog((HttpServletRequest) request, null, null, "登录失败");
        return true;
	}


	public String getMessageParam() {
		return DEFAULT_MESSAGE_PARAM;
	}
}